package cn.com.lyj6851.auth.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import cn.com.lyj6851.common.properties.LoginResponseType;
import cn.com.lyj6851.common.properties.RootSecurityProperties;
import cn.com.lyj6851.common.properties.SecurityConstants;
import cn.com.lyj6851.common.util.ResultUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;

/**
 * 处理需要身份认证的请求
 */

@RestController
@Slf4j
public class Oauth2AuthenticationController {
	
    private RequestCache requestCache = new HttpSessionRequestCache();

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
    @Autowired
    private RootSecurityProperties securityProperties;

    /**
     * 当需要身份认证时，跳转到这里 "/authentication/require"
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    /* 替换原代码*/
    @RequestMapping("login")
    public ModelAndView require() {
        return new ModelAndView("login");
    }
    @RequestMapping(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
    @ResponseStatus(code = HttpStatus.UNAUTHORIZED)
    public Object requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {

        SavedRequest savedRequest = requestCache.getRequest(request, response);
        log.info("引发跳转的请求是:" + savedRequest);
        //return new ModelAndView("ftl/login");
        
        if (savedRequest != null) {
            String targetUrl = savedRequest.getRedirectUrl();
            log.info("引发跳转的请求是:" + targetUrl);   
            
            if(LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {

            	return ResultUtil.error(HttpStatus.UNAUTHORIZED.value(), "访问的服务需要身份认证，请引导用户到登录页");
            }else {
            	redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginPage());
            	/*if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
                    redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginPage());
                }*/
            }
        }
        return ResultUtil.error(HttpStatus.UNAUTHORIZED.value(), "访问的服务需要身份认证，请引导用户到登录页");
  
    }
    
    
    /**
     * 用户信息校验
     * @param authentication 信息
     * @return 用户信息
     */
    @RequestMapping("/user")
    public Object user(Authentication authentication) {
        return authentication.getPrincipal();
    }

    /**
     * 清除Redis中 accesstoken refreshtoken
     *
     * @param accesstoken  accesstoken
     * @return true/false
     */
    //@PostMapping("/removeToken")
    //@CacheEvict(value = SecurityConstants.TOKEN_USER_DETAIL, key = "#accesstoken")
    /*public R<Boolean> removeToken(String accesstoken) {
        return new R<>( consumerTokenServices.revokeToken(accesstoken));
    }*/
    
    /**
     * 下面有几种获取方法，可以查看类里面的信息
     * @param userDetails
     * @param authentication
     * @param request
     * @return
     */
    @GetMapping("/me")
    public Object getCurrentUser(@AuthenticationPrincipal UserDetails userDetails, Authentication authentication, HttpServletRequest request) throws UnsupportedEncodingException {
        // Authentication authentication1 = SecurityContextHolder.getContext().getAuthentication();
        // Authorization : bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW55IjoiaW1vb2MiLCJ1c2VyX25hbWUiOiJhZG1pbiIsImp0aSI6ImRjYzVmODIwLWUwNmYtNDYyNi1hYmMyLTAyZTljZjdkZjhmOCIsImNsaWVudF9pZCI6Im15aWQiLCJzY29wZSI6WyJhbGwiXX0.nYFBXcLBN3WNef0sooNxS0s6CaEleDGfjZh7xtTEqf4
        // 增加了jwt之后，获取传递过来的token
        // 当然这里只是其中一种的 token的传递方法，自己要根据具体情况分析
        String authorization = request.getHeader("Authorization");
        String token = StringUtils.substringAfter(authorization, "bearer ");
        log.info("jwt token", token);
        String jwtSigningKey = securityProperties.getOauth2().getJwtSigningKey();
        // 生成的时候使用的是 org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
        // 源码里面把signingkey变成utf8了
        // JwtAccessTokenConverter类，解析出来是一个map
        // 所以这个自带的JwtAccessTokenConverter对象也是可以直接用来解析的
        byte[] bytes = jwtSigningKey.getBytes("utf-8");
        Claims body = Jwts.parser().setSigningKey(bytes).parseClaimsJws(token).getBody();

        return body;
    }

}
